#include <nir.h>

 

sbit IR_INPUT=P3^3;	//外部中断引脚   P33与键盘冲突，需要临时关闭键盘扫描
sbit INFRARED_OUTPUT = P1^0; //红外发射管

unsigned char code Remote6[]={0x0d, 0x09, 0x08, 0x0a, 0x0c, 0x03, 0x0f};
//遥控器按键对应的命令码



bit irflag=0;	//接收信号标志位
unsigned char ircode[4];	//接收码值缓存区，按序存放，地址码，地址反码，键值码和键值反码

//红外接收初始化函数，定时器1用于高低电平计时，外部中断1用于检测边沿
void ISR_Init()
{
	IR_INPUT=1;		//初始化中断引脚，等待接收下降沿
	
	TMOD&=0x0F;
	TMOD|=0x10;		//定时器1为16位不可重装载模式
	AUXR&=0x3f;
	AUXR|=0x80;	 	//定时器1，12分频
					//注意定时器的精确频率计算：11.0592/12MHz，即每12/11.0592计数器加1
	
	TR1=0;	//定时器1关闭
	ET1=0;	//定时器1中断允许
	
	IT1=1;	//外部中断1设为下边沿触发	
	EX1=1;	//外部中断1允许

 
}		

//获取高电平时间
unsigned int GetHighTime()
{
	TH1=0;	//复位计数器
	TL1=0;
	TR1=1;	//打开定时器1
	while(IR_INPUT)
	{
		if(TH1>0x40)	//超出规定时间即信号有误，则不返回高电平时间
		{
			break;
		}
	}
	TR1=0;
	
	return(TH1*256+TL1);
}

//获取低电平时间
unsigned int GetLowTime()
{
	TH1=0;
	TL1=0;
	TR1=1;
	while(!IR_INPUT)
	{
		if(TH1>0x40)
		{
			break;
		}
	}
	TR1=0;
	
	return(TH1*256+TL1);
}


//外部中断1函数
void EXINT_ISR() interrupt 2
{
	unsigned char i, j;
	unsigned int time;
	unsigned char byte;
	EX1=0;	//外部中断1关闭，防止多次调用
	
	//引导码确认
	time=GetLowTime();	//先获取低电平，因为接收与发送电平相反
	if((time<7833)||(time>8755))	//12/11.0592*7833≈8500us,12/11.0592*8755≈9500us,协议规定9ms
	{
		IE1=0;	//外部中断1标志位清零
		EX1=1;
		return;		//不在规定范围，引导码有误
	}
	time = GetHighTime();
	if((time<3686)||(time>4608))	//12/11.0592*3686≈4000us,12/11.0592*4608≈5000us，协议规定4.5ms
	{
		IE1=0;
		EX1=1;
		return;
	}
	
	//，引导码正确，开始获取地址码，地址反码，键值码，键值反码并存入缓存区
	for(i=0;i<4;i++)
	{
		for(j=0;j<8;j++)
		{
			time=GetLowTime();
			if((time<313)||(time>718))	//推导与上述类似
			{
				IE1=0;
				EX1=1;
				return;
			}
			
			time=GetHighTime();
			if((time>313)&&(time<718))
			{
				byte>>=1;
			}
			else if((time>1345)&&(time<1751))
			{
				byte>>=1;
				byte|=0x80;
			}
			else
			{
				IE1=0;
				EX1=1;
				return;
			}
		} 
		ircode[i]=byte;	//把获取到的8位码存入缓存数组
	}
	
	irflag=1;//成功接收到码值
	IE1=0;
	EX1=1;	//外部中断1开启
}


void DelayUs(unsigned int n)	//@11.0592MHz
{
	while(n--){//n us
		_nop_();
		_nop_();
		_nop_();
	}
}

/*
函数功能: 发送38KHZ的载波
函数参数：
u32 time_us 持续的时间
u8 flag 1表示发送38KHZ载波，0表示不发送
*/
void InfraredSend38KHZ(unsigned int time_us,unsigned char flag)
{
    unsigned int i;
    if(flag)
    {
        //发送38KHZ载波
        for(i=0;i<time_us/13;i++)
        {
            INFRARED_OUTPUT=!INFRARED_OUTPUT;
            DelayUs(13);
        }
    }
    else
    {
        INFRARED_OUTPUT=1;//关闭红外线发射管
        DelayUs(time_us);
    }
}


/*
函数功能: NEC协议编码发送
函数参数: 
				u8 user 用户码
				u8 key  按键码
先发低位
按键反码+按键码+用户反码+用户码
*/
void InfraredNECSend(unsigned char user,unsigned char key)
{
	unsigned char i;
	 /*1. 组合发送的数据*/
	unsigned int  _data=((~key&0xFF)<<24)|((key&0xFF)<<16)|((~user&0xFF)<<8)|((user&0xFF)<<0);
		
	 /*2. 发送引导码*/
	InfraredSend38KHZ(9000,1);//发送38KHZ载波
	InfraredSend38KHZ(4500,0);//不发送
	
	/*3. 发送32位数据*/
	 for(i=0;i<32;i++)
	 {
			InfraredSend38KHZ(560,1); //间隔时间
			if(_data&0x01)InfraredSend38KHZ(1685,0); //发送1
			else InfraredSend38KHZ(560,0); //发送0
		  _data>>=1;
	 }
	 InfraredSend38KHZ(560,1); //间隔时间
}
